﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using StressTesterCommon;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Input;
using Microsoft.Win32;
using System.Windows;
using StressServer_UI;

namespace StressServer.ViewModel
{
    public class TestViewModel : INotifyPropertyChanged
    {
        #region NotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string info)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(info));
            }
        }
        #endregion
        #region Constructor
        public TestViewModel(Test Test, ServerViewModel Parent)
        {
            _Test = Test;
            RefreshQueries();
            _CommandRemoveCurrentQuery = new RelayCommand(ExecuteRemoveCurrentQuery) { IsEnabled = true };
            _CommandMoveUpCurrentQuery = new RelayCommand(ExecuteMoveUpCurrentQuery) { IsEnabled = true };
            _CommandMoveDownCurrentQuery = new RelayCommand(ExecuteMoveDownCurrentQuery) { IsEnabled = true };
            _CommandAddQuery = new RelayCommand(ExecuteAddQuery) { IsEnabled = true };
            _CommandNewTest = new RelayCommand(ExecuteNewTest) { IsEnabled = true };
            _CommandSetOutput = new RelayCommand(ExecuteSetOutput) { IsEnabled = true };
            _CommandImportTraceFile = new RelayCommand(ExecuteImportTraceFile) { IsEnabled = true };
            _CommandShowTraceFile = new RelayCommand(ExecuteShowTraceFile) { IsEnabled = true };
            _CommandSelectTraceFile = new RelayCommand(ExecuteSelectTraceFile) { IsEnabled = true };
           
        }
        #endregion
        #region Members

        public int TestThreadCount
        {
            get { return _Test.TestThreadCount; }
            set { if (value != _Test.TestThreadCount) { _Test.TestThreadCount = value; OnPropertyChanged("TestThreadCount"); } }
        }
        public bool DoClearCache
        {
            get { return _Test.DoClearCache; }
            set { if (value != _Test.DoClearCache) { _Test.DoClearCache = value; OnPropertyChanged("DoClearCache"); } }
        }

        private ServerViewModel _Parent;
        public ServerViewModel Parent
        {
            get { return _Parent; }
            set { _Parent = value; }
        }
        private TraceFileImportWindow _TraceWindow;
        private QuerySourceTraceFile _TraceFileSource = null;
        public QuerySourceTraceFile TraceFileSource
        {
            get { return _TraceFileSource; }
            set { if (_TraceFileSource != value) { _TraceFileSource = value; OnPropertyChanged("TraceFileSource"); } }
        }
        private Test _Test;
        public Test Test
        {
            get { return _Test; }
            set { _Test = value; }
        }
        private ObservableCollection<QueryViewModel> _Queries;
        public ObservableCollection<QueryViewModel> Queries
        {
            get { return _Queries; }
        }
        private static QueryViewModel _CurrentQuery = null;
        public bool HasCurrentQuery
        {
            get { if (_CurrentQuery == null) { return false; } else { return true; } }
        }
        public QueryViewModel CurrentQuery
        {
            get
            {
                return _CurrentQuery;
            }
            set
            {
                if (value != _CurrentQuery) { _CurrentQuery = value; OnPropertyChanged("CurrentQuery"); OnPropertyChanged("HasCurrentQuery"); }
            }
        }
        public string Name
        {
            get { return _Test.Name; }
            set 
            { 
                if (value != _Test.Name) 
                { 
                    _Test.Name = value; 
                    OnPropertyChanged("Name"); 
                } 
            }
        }
        public string ServerName
        {
            get { return _Test.Connection.Server; }
            set { if (value != _Test.Connection.Server) { _Test.Connection.Server = value; OnPropertyChanged("ServerName"); } }
        }

        public bool UniqueQueriesOnly
        {
            get { return _TraceFileSource.UniqueQueriesOnly; }
            set { if (value != _TraceFileSource.UniqueQueriesOnly) { _TraceFileSource.UniqueQueriesOnly = value; OnPropertyChanged("UniqueQueriesOnly"); } }
        }
        public string TraceFilePath
        {
            get { return _TraceFileSource.TraceFilePath; }
            set { if (value != _TraceFileSource.TraceFilePath) { _TraceFileSource.TraceFilePath = value; OnPropertyChanged("TraceFilePath"); } }
        }
        public string DatabaseName
        {
            get { return _Test.Connection.Database; }
            set { if (value != _Test.Connection.Database) { _Test.Connection.Database = value; OnPropertyChanged("DatabaseName"); } }
        }

        public int TotalQueries
        {
            get { return _Test.TotalNumberOfQueries; }
        }
        public int DelayFrom
        {
            get { return _Test.MSDelayBetweenQueriesFrom; }
            set { if (value != _Test.MSDelayBetweenQueriesFrom) { _Test.MSDelayBetweenQueriesFrom = value; OnPropertyChanged("DelayFrom"); } }

        }
        public int DelayTo
        {
            get { return _Test.MSDelayBetweenQueriesTo; }
            set { if (value != _Test.MSDelayBetweenQueriesTo) { _Test.MSDelayBetweenQueriesTo = value; OnPropertyChanged("DelayTo"); } }

        }
        public int Repeat
        {
            get { return _Test.TimesToRepeat; }
            set { if (value != _Test.TimesToRepeat) { _Test.TimesToRepeat = value; OnPropertyChanged("Repeat"); } }
        }

        public bool IsRandom
        {
            get { if (_Test.QueryPickMethod == QueryPickMode.Random) { return true; } else { return false; } }
            set { if (value) { _Test.QueryPickMethod = QueryPickMode.Random; } else { _Test.QueryPickMethod = QueryPickMode.Sequential; OnPropertyChanged("IsRandom"); } }
        }

        public bool IsSequential
        {
            get { if (_Test.QueryPickMethod == QueryPickMode.Random) { return false; } else { return true; } }
            set { if (!value) { _Test.QueryPickMethod = QueryPickMode.Random; } else { _Test.QueryPickMethod = QueryPickMode.Sequential; } OnPropertyChanged("IsSequential"); }
        }

        public string OutputPath
        {
            get { return _Test.OutputPath; }
            set { if (value != _Test.OutputPath) { _Test.OutputPath = value; OnPropertyChanged("OutputPath"); } }
        }

        public bool Append
        {
            get { return _Test.AppendToOutput; }
            set { if (_Test.AppendToOutput != value) { _Test.AppendToOutput = value; OnPropertyChanged("Append"); } }
        }
        #endregion
        #region Command declarations
        private ICommand _CommandSelectTraceFile;
        public ICommand CommandSelectTraceFile
        {
            get { return _CommandSelectTraceFile; }
        }
        private ICommand _CommandShowTraceFile;
        public ICommand CommandShowTraceFile
        {
            get { return _CommandShowTraceFile; }
        }
        private ICommand _CommandImportTraceFile;
        public ICommand CommandImportTraceFile
        {
            get { return _CommandImportTraceFile; }
        }

        private ICommand _CommandSetOutput;
        public ICommand CommandSetOutput
        {
            get { return _CommandSetOutput; }
        }
        private ICommand _CommandNewTest;
        public ICommand CommandNewTest
        {
            get { return _CommandNewTest; }
        }

        private ICommand _CommandAddQuery;
        public ICommand CommandAddQuery
        {
            get { return _CommandAddQuery; }
        }
        private ICommand _CommandRemoveCurrentQuery;
        public ICommand CommandRemoveCurrentQuery
        {
            get { return _CommandRemoveCurrentQuery; }
        }

        private ICommand _CommandMoveUpCurrentQuery;
        public ICommand CommandMoveUpCurrentQuery
        {
            get { return _CommandMoveUpCurrentQuery; }
        }

        private ICommand _CommandMoveDownCurrentQuery;
        public ICommand CommandMoveDownCurrentQuery
        {
            get { return _CommandMoveDownCurrentQuery; }
        }
        #endregion
        #region Command implementations
        public void ExecuteSelectTraceFile()
        {

            OpenFileDialog dlg = new OpenFileDialog();
            dlg.DefaultExt = ".trc";
            dlg.Title = "Select trace file";
            dlg.Filter = "TRACE files (*.trc)|*.trc";
            Nullable<bool> Res = dlg.ShowDialog();
            if (Res == true)
            {
                this.TraceFilePath = dlg.FileName;

            }
        }
        public void ExecuteShowTraceFile()
        {
            if (this.DatabaseName == null || this.DatabaseName == "")
            {
          
                MessageBox.Show("Set target database name for test under the 'General' tab. The import needs this to select the correct queries from the trace file.", "Database missing");
                return;
            }
            _TraceFileSource = new QuerySourceTraceFile(_Test);
            _TraceWindow = new TraceFileImportWindow();
            _TraceWindow.DataContext = this;
            _TraceWindow.Show();

        }
        public void ExecuteImportTraceFile()
        {
            _Test.Queries = _TraceFileSource.GetQueries();
            RefreshQueries();
            _TraceWindow.Close();
        }
        public void ExecuteRemoveCurrentQuery()
        {
            if (CurrentQuery != null)
            {
                int Idx = Queries.IndexOf(CurrentQuery);
                _Test.Queries.Remove(CurrentQuery.Query);
                Queries.Remove(CurrentQuery);
                
                if (Idx < Queries.Count)
                {
                    CurrentQuery = Queries[Idx];
                }
                else
                {
                    CurrentQuery = null;
                }

            }
        }
        public void ExecuteMoveUpCurrentQuery()
        {
            if (CurrentQuery != null)
            {
                int IdxCurrent = Queries.IndexOf(CurrentQuery);
                if (IdxCurrent > 0)
                {
                    int IdxNew = IdxCurrent--;
                    Query Q = _Test.Queries[IdxCurrent];
                    _Test.Queries.RemoveAt(IdxCurrent);
                    _Test.Queries.Insert(IdxNew, Q);
                    Queries.Move(IdxCurrent, IdxNew);
                   
                }
            }
        }
        public void ExecuteMoveDownCurrentQuery()
        {
            if (CurrentQuery != null)
            {
                int IdxCurrent = Queries.IndexOf(CurrentQuery);
                int IdxNew = IdxCurrent++;
                if (IdxNew+1 < Queries.Count)
                {
                    Query Q = _Test.Queries[IdxCurrent];
                    _Test.Queries.RemoveAt(IdxCurrent);
                    _Test.Queries.Insert(IdxNew, Q);
                    Queries.Move(IdxCurrent, IdxNew);
                }
                
            }
        }
        public void ExecuteAddQuery()
        {
            int Idx;
            if (CurrentQuery == null)
            {
                Idx = Queries.Count;
            }
            else
            {
                Idx = Queries.IndexOf(CurrentQuery);
                             
            }
            Query Q = new Query();
            Q.Name = "New query";
            Q.Text = "Add query text here";
            QueryViewModel VQ = new QueryViewModel(Q);
            Queries.Insert(Idx, VQ);
            _Test.Queries.Insert(Idx, Q);
            CurrentQuery = VQ;
        }
        public void ExecuteNewTest()
        {
            _Test = new Test();

        }
        public void ExecuteSetOutput()
        {
            SaveFileDialog dlg = new SaveFileDialog();
            dlg.DefaultExt = ".txt";
            dlg.Title = "Select / create output file";
            dlg.CheckPathExists = true;
            dlg.CreatePrompt = true;
            dlg.Filter = "TEXT files (*.txt)|*.txt";
            Nullable<bool> Res = dlg.ShowDialog();
            if (Res == true)
            {
                this.OutputPath= dlg.FileName;
            }
        }
        #endregion
        #region methods
        private void RefreshQueries()
        {
            _Queries = new ObservableCollection<QueryViewModel>();
            foreach (Query Q in _Test.Queries)
            {
                QueryViewModel QV = new QueryViewModel(Q);
                _Queries.Add(QV);
            }
            OnPropertyChanged("Queries");
        }
        #endregion

    }
}
